<?php
class XAssert{
	public static function assertEquals($expected, $actual, $message = null){
		if(is_array($expected) && is_array($actual)){
			self::assertArrayEquals($expected, $actual);
			return;
		}
		if(is_object($expected) && is_object($actual)){
			self::assertObjectEquals($expected, $actual);
			return;
		}				
		if($expected !== $actual){
			if(is_null($message)){				
				self::fail("expected {$expected}, but was {$actual}");
				return;
			}
			self::fail($message);
		}
	}
	
	public static function assertArrayEquals(array $expected, $actual){
		if(!is_array($actual)){
			self::fail("expected an array, but was not");
		}
		$message = "two arrays not equal";
		foreach($actual as $key => $value){
			$expectedValue = array_shift($expected);
			self::assertEquals($expectedValue, $value, $message);
		}
	}
	
	public static function assertObjectEquals($expected, $actual){
		if(!is_object($actual)){
			self::fail("expected an object, but was not");
		}
		$expectedClass = get_class($expected);
		$class = get_class($actual);
		if($expectedClass != $class){
			self::fail("expected class {$expectedClass}, but was {$class}");
		}	
		$message = "two objects of class {$expectedClass} not equal";
		if(method_exists($expectedClass, 'equals')){
			self::assertEquals(true, $expected->equals($actual), $message);
		}	
		if(method_exists($expectedClass, '__toString')){
			self::assertEquals($expected->__toString(), $actual->__toString(), $message);
		}
		if(method_exists($expectedClass, 'asArray')){
			self::assertEquals($expected->asArray(), $actual->asArray(), $message);
		}
		if($expected !== $actual){
			self::fail($message);
		}
	}
	
	public static function assertSame($expected, $actual){
		$expectedRef = &$expected;
		$actualRef = &$actual;
		if($expectedRef !== $actualRef){
			self::fail("two objects don't have the same reference.");
		}
	}
	
	public static function fail($message){
		throw new XAssertFailedException($message);
	}
}
?>